<?php
//
//	file: includes/class_advnot_email.php
//	begin: 2006-07-10
//	$Author: christopher $
//	$Revision: 29 $
//	$Date: 2008-07-19 15:59:35 +0000 (Sat, 19 Jul 2008) $
//	license: http://opensource.org/licenses/gpl-license.php GNU General Public License (GPL)
//
//	description: reworked email class to simplify processes for sending emails as well as add new options
//	based on original phpBB2 emailer class and Brent R. Matzelle's PHPMailer library

if ( !defined('IN_PHPBB') )
{
	die('Hacking attempt');
}

class advnot_email
{
	// string/integer vars
	var $subject, $use_smtp, $template, $tpl_file, $charset;
	// array vars
	var $users, $headers, $vars, $notify_type;

	// @constructor initialize
	function __constructor()
	{
		global $config;

		// Here, we're using either the PHP mail() function or the SMTP mailer...no sendmail at this time!
		// If on a Windows server, we have to use smtp
		$this->use_smtp = (preg_match('/[c-z]:\\\.*/i', getenv('PATH')) && !$config->data['smtp_delivery']) ? 1 : $config->data['smtp_delivery'];
	}

	// backward compatibility
	function advnot_email()
	{
		return $this->__constructor();
	}

	// @public empties fields
	function reset($notify_type='email')
	{
		global $config, $user;

		$this->users = $this->vars = array();
		$this->subject = $this->subtitle = $this->template = $this->tpl_file = '';

		$this->notify_type = 'user_notify_' . $notify_type;
		$this->charset = ($user->lang('ENCODING')) ? $user->lang('ENCODING') : 'iso-8859-1';

		$this->headers = array(
			'From' => $config->data['site_name'] . ' <' . $config->data['board_email'] . '>',
			'Reply-to' => $config->data['site_name'] . ' <' . $config->data['board_email'] . '>',
			'Content-type' => 'text/plain; charset=' . $this->charset,
			'Message-ID' => '<' . md5(uniqid(time())) . '@' . $config->data['server_name'] . '>',
			'MIME-Version' => '1.0',
			'Content-transfer-encoding' = '8bit',
			'Date' => date('r', time()),
			'X-Priority' => 3,
			'X-MSMail-Priority' => $this->ms_priority(),
		);

		return;
	}

	// @public adds user to addressed users
	function add_user($user_to, $type='to')
	{
		global $config;

		// send only to users who want the notification
		if ( ($user_to['user_active'] || $config->data['advnot_send_inactive']) && $user_to['user_notify'] && $user_to[$this->notify_type])
		{
			$user_to['user_lang'] = empty($user_to['user_lang']) ? $config->data['default_lang'] : $user_to['user_lang'];

			// group recipients according to language and email preference
			$this->users[$user_to['user_lang'] . '.' . $user_to['user_email_type']][$type][$user_to['username']] = $user_to['user_email'];
		}
	}

	// @public add an email header
	function add_headers($headers)
	{
		foreach ($headers as $key => $var)
		{
			$this->headers[$key] = $var;
		}
	}

	// @public adds template variables
	function assign_vars($vars)
	{
		$this->vars = array_merge($this->vars, $vars);
	}

	// @public prepare the subject
	function set_subject($subject='', $subtitle='')
	{
		global $user;

		$subject = trim(htmlspecialchars($subject));

		if (!empty($subject))
		{
			$this->subject = trim(preg_replace('#[\n\r]+#s', '', $subject));

			$subtitle = trim(htmlspecialchars($subtitle));
			if (!empty($subtitle))
			{
				$this->subject .= ": " . trim(preg_replace('#[\n\r]+#s', '', $subtitle));
			}
		}
	}

	// @public prepares a message body
	function set_message($message='')
	{
		global $config;

		$encoding = $this->charset;
		$message = trim($message);

		if (empty($message))
		{
			return;
		}

		// first, convert all bbcode to html if allowed, otherwise we remove it completely
		if ($config->data['advnot_allow_bbcode'] && $config->data['allow_bbcode'])
		{
			// we are relying on the current bbcode schema for this to work
			// without having to modify the allowed bbcodes when new ones are added
			include($config->url('includes/bbcode'));
			$message = bbencode_second_pass(bbencode_first_pass($message, NOTIFY_BBCODE_UID), NOTIFY_BBCODE_UID);
		}
		else
		{
			$message = _clean_bbcode($message);
		}
		// now, we censor the messages
		$message = _censor($message);

		// let's create an html version of the message, if it is allowed
		$message_html = $message_text = '';
		if($config->data['advnot_allow_html'] && $config->data['allow_html'])
		{
			// This is taken from includes/functions_post.php
			$message_html = stripslashes($message);
			$html_match = '#<[^\w<]*(\w+)((?:"[^"]*"|\'[^\']*\'|[^<>\'"])+)?>#';
			$matches = array();

			$message_split = preg_split($html_match, $message_html);
			preg_match_all($html_match, $message_html, $matches);

			$message_html = '';

			foreach ($message_split as $part)
			{
				$tag = array(array_shift($matches[0]), array_shift($matches[1]), array_shift($matches[2]));
				$message_html .= _html_entities_encode($part) . clean_html($tag);
			}

			$message_html = addslashes($message_html);
			$message_html = str_replace('&quot;', '\&quot;', $message_html);
		}
		else
		{
			$message_html = _html_entities_encode($message);
		}

		// here we create a text-only version of the message
		$message_text = _clean_html($message);

		// lastly, we encode properly!
		// this is taken from the vanilla phpbb emailer class (which came from php.net)
		if ($encoding !== 'iso-8859-1')
		{
			// define start delimimter, end delimiter and spacer
			$end = "?=";
			$start = "=?$encoding?B?";
			$spacer = "$end\r\n $start";

			// determine length of encoded text within chunks and ensure length is even
			$length = 75 - strlen($start) - strlen($end);
			$length = floor($length / 2) * 2;

			// encode the string and split it into chunks with spacers after each chunk
			$message_text = chunk_split(base64_encode($message_text), $length, $spacer);
			$message_html = chunk_split(base64_encode($message_html), $length, $spacer);

			// remove trailing spacer and add start and end delimiters
			$message_text = preg_replace('#' . preg_quote($spacer, '#') . '$#', '', $message_text);
			$message_html = preg_replace('#' . preg_quote($spacer, '#') . '$#', '', $message_html);

			$message_text = $start . $message_text . $end;
			$message_html = $start . $message_html . $end;
		}

		$this->vars['MESSAGE_HTML'] = $message_html;
		$this->vars['MESSAGE_TEXT'] = $message_text;

		return;
	}

	// @public sets the template name for later use
	function set_tpl($template)
	{
		$this->template = $template;

		return;
	}

	// @public send post
	function send ()
	{
		global $config;
		global $error;

		if ($this->notify_type == 'user_notify_email')
		{
			$this->set_from();
		}

		// check for errors
		if (empty($this->users))
		{
			_error('pm_no_recipients');
		}
		if (empty($this->subject))
		{
			_error('pm_no_subject');
		}
		if (empty($this->template))
		{
			_error('pm_no_template');
		}

		// let whatever called this deal with the error message!
		if ( $error )
		{
			return false;
		}

		foreach ($this->users as $format1)
		{
			$format = explode('.',$format1);
			$userlang = $format[0];
			$emailtype = $this->set_type($format[1]);
			$this->get_tpl($userlang, $emailtype);
			$message = $this->prepare($userlang, $emailtype);

			// build header
			$main_header = $this->build_header();
			$header = $this->first_header($main_header, $format1);

			// send message
			foreach($this->users[$format1]['to'] as $name => $email)
			{
				$to = ($config->data['advnot_show_username']) ? $name . ' <' . $email . '>' : $email;

				if ( $this->use_smtp )
				{
					if ( !defined('SMTP_INCLUDED') )
					{
						include($config->url('includes/smtp'));
					}
					$result = smtpmail($to, $this->subject, $message, $header);
				}
				else
				{
					$empty_to_header = ($to == '') ? TRUE : FALSE;
					$to = ($to == '') ? (($config->data['sendmail_fix']) ? ' ' : 'Undisclosed-recipients:;') : $to;

					$result = @mail($to, $this->subject, preg_replace("#(?<!\r)\n#s", "\n", $message), $header);

					if (!$result && !$config->data['sendmail_fix'] && $empty_to_header)
					{
						$to = ' ';
						$config->set('sendmail_fix', '1', true);
						$result = @mail($to, $this->data['subject'], preg_replace("#(?<!\r)\n#s", "\n", $message), $header);
					}
				}
				// Did it work?
				if (!$result)
				{
					message_die(GENERAL_ERROR, 'Failed sending email :: ' . (($this->use_smtp) ? 'SMTP' : 'PHP') . ' :: ' . $result, '', __LINE__, __FILE__);
				}
				// Remove (b)cc list(s) for subsequent emails
				$header = $main_header;
			}
		}
		return;
	}

	// @private prepares headers for sending
	function build_header()
	{
		global $config;

		$headers = "";
		foreach ($this->headers as $key => $value)
		{
			$headers .= "$key: $value\n";
		}
		return $headers;
	}

	// @private creates a "first" header for (b)cc fields
	function first_header($headers, $format)
	{
		if ($this->users['cc'])
		{
			$headers .= "Cc: " . explode(', ', $this->users[$format]['cc']) . "\n";
		}
		if ($this->users['bcc'])
		{
			$headers .= "Bcc: " . explode(', ', $this->users[$format]['bcc']) . "\n";
		}
		return $headers;
	}

	// @private gets the proper template file
	function get_tpl($lang, $type)
	{
		global $config;

		$tpl_file = $config->url('language/lang_' . $lang . '/email/' . $this->template . '.' . $type . '.tpl');

		if (!@file_exists(@phpbb_realpath($tpl_file)))
		{
			$tpl_file = $config->url('language/lang_' . $config->data['default_lang'] . '/email/' . $this->template . '.' . $type . '.tpl');

			if (!@file_exists(@phpbb_realpath($tpl_file)))
			{
				message_die(GENERAL_ERROR, 'Cannot find template file ' . $tpl_file, __LINE__, __FILE__);
			}
		}

		if (!($fd = @fopen($tpl_file, 'r')))
		{
			message_die(GENERAL_ERROR, 'Cannot access template file ' . $tpl_file, __LINE__, __FILE__);
		}

		$this->tpl_file = fread($fd, filesize($tpl_file));
		fclose($fd);

		return;
	}

	// @private changes sender to the current user
	function set_from()
	{
		global $config, $user;
		$this->headers['From'] = ($config->data['advnot_show_username']) ? $user->data['username'] . ' <' . $user->data['user_email'] . '>' : $user->data['user_email'];
	}

	// @private sets the email type
	function set_type($type)
	{
		global $config;

		$html_on = ($config->data['advnot_allow_html'] && !empty($this->vars['MESSAGE_HTML'])) ? true : false;
$this->headers['Content-type'] = 'text/plain; charset=' . $this->charset;
		$header_map = array(
			'html' => 'text/html; charset=' . $this->charset,
			'both' => 'multipart/alternative; boundary=' . $boundary . '; charset=' . $this->charset,
			'text' => 'text/plain; charset=' . $this->charset,
		);

		if (($type == 'html' || $type = 'both') && $html_on)
		{
			$this->headers['Content-type'] = $header_map[$type];
			return $type;
		}

		return 'text';
	}

	// @private sets message and cleans it
	function prepare($lang, $type)
	{
		// Let's use a template!
		if($this->tpl_file)
		{
			$message = $this->tpl_file;

			// Substitute the correct vars for email
			$message = str_replace ("'", "\'", $message);
			$message = preg_replace('#\{([a-z0-9\-_]*?)\}#is', "' . $\\1 . '", $message);

			// Set vars
			reset ($this->vars);
			foreach ($this->vars as $key => $val)
			{
				$$key = $val;
			}

			eval("\$message = '$message';");

			// Clear vars
			reset ($this->vars);
			foreach ($this->vars as $key => $val)
			{
				unset($$key);
			}

			// Pull headers/subject from body and use them
			$drop_header = '';
			$match = array();
			if (preg_match('#^(Subject:(.*?))$#m', $message, $match))
			{
				$this->set_subject(trim($match[2]));
				$drop_header .= '[\r\n]*?' . preg_quote($match[1], '#');
			}
			$this->subject('No Subject');

			if (preg_match('#^(Charset:(.*?))$#m', $message, $match))
			{
				$this->headers['Charset'] = (trim($match[2]) != '') ? trim($match[2]) : $this->headers['Charset'];
				$drop_header .= '[\r\n]*?' . preg_quote($match[1], '#');
			}

			if ($drop_header != '')
			{
				$message = trim(preg_replace('#' . $drop_header . '#s', '', $message), true);
			}
		}
		else
		{
			// if we have an HTML message
			if ($config->data['advnot_allow_html'])
			{
				$this->headers['Content-type'] = 'multipart/alternative; charset="' . $this->charset . '"; boundary="' . $this->boundary . '"';
				$message = '--' . $this->boundary . "\nContent-type: text/plain\n" . $this->vars['MESSAGE_TEXT'] . "\n\n--" . $this->boundary . "\nContent-type: text/html\n" . $this->vars['MESSAGE_HTML'] . "\n--" . $this->boundary . "--\n";
			}
			//Plain Email message
			else
			{
				$message = $this->vars['MESSAGE_TEXT'];
			}
		}

		return $message;
	}

	// @private simple function that labels priority flag for ms outlook
	function ms_priority()
	{
		if ($this->headers['X-Priority'] != 3)
		{
			return (($this->headers['X-Priority'] < 3)) ? 'Low' : 'High';
		}
		return 'Normal';
	}
}

/*
A simple process for a forum notification should be:
$vars = array(
	'FORUM_NAME' => $forum_name,
	...
);
$users = '3,6,12,89,163,...,821';

$notify = new advnot_parent('email');
$notify->add_users($users, 'bcc');
$notify->template('advnot_forum', $vars);
$notify->send();
*/
?>